// bmp085.c
//

#include <avr/io.h>

#include "../mcu/config.h"
#include "../mcu/types.h"
#include "../mcu/twi_master.h"
#include "../mcu/serial.h"
#include "../mcu/delay.h"
#include "../mcu/timer.h"

#include "common.h"
#include "bmp085.h"


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

short			gAC1;
short			gAC2;
short			gAC3;
unsigned short	gAC4;
unsigned short	gAC5;
unsigned short	gAC6;
short			gB1;
short			gB2;
long			gB5;
short			gMb;
short			gMc;
short			gMd;


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

int bmp085_read(unsigned char reg_addr, unsigned char * buf, int buflen)
{
	int i;

	//
//	i2c_start_wait(BMP085_I2C_ADDR + I2C_WRITE);
	i2c_start(BMP085_I2C_ADDR + I2C_WRITE);
	i2c_write(reg_addr);


	//
	i2c_rep_start(BMP085_I2C_ADDR + I2C_READ);


	for( i = 0; i < buflen - 1; i++ )
		buf[i] = i2c_readAck();
	 buf[i] = i2c_readNak();

	i2c_stop();


	return 0;
}

int bmp085_write(unsigned char reg_addr, unsigned char * buf, int buflen)
{
	int i;

//	i2c_start_wait(BMP085_I2C_ADDR + I2C_WRITE);
	i2c_start(BMP085_I2C_ADDR + I2C_WRITE);
	i2c_write(reg_addr);

	for( i = 0; i < buflen; i++ )
		i2c_write(buf[i]);

	i2c_stop();

	return 0;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//

int bmp085_init()
{
	unsigned char data[BMP085_PROM_DATA_LEN];
	// reset
	BMP085_PORT &= ~(1 << BMP085_XCLR);	// XCLR is LOW
	wait_1ms(100);
	BMP085_PORT |= (1 << BMP085_XCLR);	// XCLR is HIGH
	wait_1ms(100);

	// read calibration coefficients
	bmp085_read(BMP085_PROM_START_ADDR, data, BMP085_PROM_DATA_LEN);

	gAC1 = (short)((((unsigned short)data[0]) << 8) | (unsigned short)data[1]);
	gAC2 = (short)((((unsigned short)data[2]) << 8) | (unsigned short)data[3]);
	gAC3 = (short)((((unsigned short)data[4]) << 8) | (unsigned short)data[5]);
	
	gAC4 = (((unsigned short)data[ 6]) << 8) | (unsigned short)data[ 7];
	gAC5 = (((unsigned short)data[ 8]) << 8) | (unsigned short)data[ 9];
	gAC6 = (((unsigned short)data[10]) << 8) | (unsigned short)data[11];

	gB1 = (short)((((unsigned short)data[12]) << 8) | (unsigned short)data[13]);
	gB2 = (short)((((unsigned short)data[14]) << 8) | (unsigned short)data[15]);

//	gMb = (short)((((unsigned short)data[16]) << 8) | (unsigned short)data[17]);
	gMb = 0;
	gMc = (short)((((unsigned short)data[18]) << 8) | (unsigned short)data[19]);
	gMd = (short)((((unsigned short)data[20]) << 8) | (unsigned short)data[21]);

	return 0;
}

short bmp085_calc_temperature(unsigned long ut)
{
	long x1,x2;
	s16 t;

	x1 = (((long)ut - (long) gAC6) * (long) gAC5) >> 15;
	x2 = ((long)gMc << 11) / (x1 + gMd);
	gB5 = x1 + x2;
	t = ((gB5+8)>>4);

	return t;
}

long bmp085_calc_pressure(unsigned long up)
{
	long x1,x2,x3,b3,b6,p;
	unsigned long b4,b7;

	b6 = gB5 - 4000L;
	x1 = (b6 * b6) >> 12;	 	 
	x1 *= gB2;
	x1 >>= 11;

	x2 = (gAC2 * b6);
	x2 >>= 11;
	x3 = x1 + x2;
	b3 = (((((long)gAC1 ) * 4 + x3) << BMP085_0SS) + 2) >> 2;

	x1 = (gAC3 * b6) >> 13;
	x2 = (gB1 * ((b6*b6) >> 12) ) >> 16;
	x3 = ((x1 + x2) + 2) >> 2;
	b4 = (gAC4 * (unsigned long) (x3 + 32768L)) >> 15;
	b7 = ((unsigned long)(up - b3) * (50000L >> BMP085_0SS));   

	if( b7 < (unsigned long)0x80000000 ) 
		p = (b7 << 1) / b4;
	else
		p = (b7 / b4) << 1;

	x1 = p >> 8;
	x1 *= x1;
	x1 = (x1 * 3038L) >> 16;
	x2 = (p * -7357L) >> 16;
	p += ((x1 + x2 + 3791L) >> 4);	// p in Pa 

	return p;
}

unsigned short bmp085_measure_temperature()
{
	unsigned char data[2];
	unsigned char type = BMP085_T_MEASURE;

	bmp085_write(BMP085_CTRL_MEAS_REG, &type, 1);
	do
	{
		wait_1ms(1);

	} while( ! (BMP085_PIN & (1 << BMP085_EOS)) );
	bmp085_read(BMP085_ADC_OUT_MSB_REG, data, 2);

	return ((((unsigned short)data[0]) << 8) + ((unsigned short)data[1]));
}

unsigned long bmp085_measure_pressure()
{
	unsigned char data[3];
	unsigned char type = BMP085_P_MEASURE | (BMP085_0SS << 6);
	unsigned long p;

	bmp085_write(BMP085_CTRL_MEAS_REG, &type, 1);
	do
	{
		wait_1ms(1); 
	} while( ! (BMP085_PIN & (1 << BMP085_EOS)) );
	bmp085_read(BMP085_ADC_OUT_MSB_REG, data, 3);

	p = (((unsigned long)data[0]) << 16) | (((unsigned long)data[1]) << 8) | (unsigned long)data[2];
	p = (p >> (8 - BMP085_0SS));

	return p;
}
